<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/12/3
 * Time: 18:41
 */
namespace app\weixin\controller;


use app\common\config\weixin_config;
use app\common\helper\appmenu_stat_helper;
use app\common\helper\appmsg_helper;
use app\common\helper\autoreply_helper;
use app\common\helper\emotion_helper;
use app\common\helper\index_msg_helper;
use app\common\helper\key_stat_helper;
use app\common\helper\open_card_helper;
use app\common\helper\user_helper;
use app\common\model\SendQueue;
use app\common\model\SendThread;
use app\common\model\User;
use app\common\model\WxRequestLog;
use app\common\widget\appmsg\appmsg_widget;
use app\common\widget\message\message_widget;
use app\common\widget\subscribe_stat\subscribe_stat_widget;
use app\common\widget\weixin\weixin_widget;
use think\facade\Cache;
use think\facade\Log;
use think\facade\Request;

class Index
{
    // 用户
    public $user_id;
    public $company_id;
    public $open_card_id;
    public $open_card_info;
    public $user_info;

    // 信息来自哪个客户
    public $from_username = '';
    // 处理接收的信息的公众号名字
    public $service_name = '';

    // 用户此次发送过来的消息
    public $req_msg = '';
    // 请求的消息类型 text文本 location 地理位置
    public $req_msg_type = 'text';
    // 请求消息的时间
    public $req_msg_timestamp = 0;
    // 原始的request
    public $ori_request = NULL;
    // 是否需要回复
    public $need_response = TRUE;

    // 是否是菜单事件
    public $is_menu_event = FALSE;

    // 是自动上报地理位置
    public $is_city_sync = FALSE;

    // 是扫描二维码
    public $is_scan  = FALSE;
    public $scene_id = 0;
    public $ori_scene_id = 0;

    // 请求的类型 1:链接  2：纯文本 3:单图文 4：多图文
    public $reply_msg_type;

    // 返回的消息 包括消息内容content_str，类型msg_type，响应类型(type)
    public $res_info = array();
    // 图文信息列表
    public $appmsg_list = array();

    public $add_time;


    /**
     * 初始化
     */
    public function __construct()
    {
        //exit('');
//        $this->mc_wr = clone $GLOBALS['mc_wr'];Cache::
        //$this->mc_wr = Cache::store('memcache')->handler();
        $this->res_info = array(
            'type'        => 0,
            'msg_type'    => 'text',
            'content_str' => '',
            'is_star'     => 0
        );
        $this->req_type = 0;
    }

    /**
     * 唯一入口
     * @param unknown_type $action
     * @param unknown_type $param
     */
    public function __call($action = "", $param = array())
    {
        try {
            // 取公司信息
            $this->parse_company();

            // 如果是首次验证
            if (Request::Get('echostr')) {
                $this->valid();
                exit;
            }

            // 处理
            $this->chat();

        } catch(\Exception $e) {
            //send_email('test@xx.com', 'weixin_service_error', var_export($e, true));

            //echo $e->getMessage();
        }
    }

    /**
     * 处理聊天请求
     */
    private function chat()
    {
        // 解析请求
        $this->parse_request();

        // 组装内置的响应
        $this->response();

        // 如果没有匹配到任何信息，则不作回复
        if (!$this->res_info['content_str'] && !$this->appmsg_list) {
            $this->need_response = FALSE;
        }

        if ($this->res_info['msg_type'] == 'text' && !$this->res_info['content_str']) {
            $this->need_response = FALSE;
        }

        if ($this->res_info['msg_type'] == 'news' && !$this->appmsg_list) {
            $this->need_response = FALSE;
        }

        // 如果不需要回复
        if (!$this->need_response) {
            exit('');
        }

        // 测试
        //$this->res_info['msg_type'] = 'text';
        //$this->res_info['content_str'] = $this->req_msg.'12121';

        $this->add_time = time();

        // 发送微信
        $this->send($this->res_info['msg_type'], $this->res_info['content_str'], $this->appmsg_list, $this->res_info['is_star']);

        exit('');
    }

    /**
     * 解析请求，获取请求信息
     */
    private function parse_request()
    {
        //exit('');
        //get post data, May be due to the different environments
//        if (ONDEV) {
            $request_data = file_get_contents('php://input');
//        } else {
//            $request_data = (isset($GLOBALS["HTTP_RAW_POST_DATA"]) && !empty($GLOBALS["HTTP_RAW_POST_DATA"])) ? $GLOBALS["HTTP_RAW_POST_DATA"] : '';
//        }
        if (empty($request_data)) {
            throw new \Exception('xml请求数据$request_data为空。');
        }

        //extract post data
        $request = simplexml_load_string($request_data, 'SimpleXMLElement', LIBXML_NOCDATA);

        $this->from_username     = filter_string(trim($request->FromUserName));
        $this->service_name      = filter_string(trim($request->ToUserName));
        $this->req_msg_type      = filter_string(trim($request->MsgType));
        $this->req_msg_timestamp = $request->CreateTime;
        // 赋值最原始的request
        $this->ori_request       = $request;
Log::write($request);
        //////////// ======= 锁开始
//        $mc_wr = clone $GLOBALS['mc_wr'];
//        $mc_ns = 'wx_api_lock';
//        $mc_key = 'api_'.$this->req_msg_timestamp;
//        $wx_api_lock = $mc_wr->NS($mc_ns, 1)->get($mc_key);
//        if ($wx_api_lock == 1) {
//            exit('');
//        }
//        $mc_wr->NS($mc_ns, 1)->set($mc_key, 1, 2, 1);
        //////////// ======= 锁结束
        ///
//        if (ONDEV) {
//            if (strpos($request_data, 'LOCATION') === false) {
//                // 记录所有的交互log，因location上报的log太多了，直接屏蔽location
//                $wx_resquest_log = array(
//                    'content' => $request_data
//                );
//                $tmp_msg_type = $this->req_msg_type;
//                if (strtolower($this->req_msg_type) == 'event') {
//                    $tmp_msg_type .= '_'.strtolower($request->Event);
//                }
//                $wx_resquest_log['msg_type'] = $tmp_msg_type;
//
//                _model('wx_resquest_log')->create($wx_resquest_log);
//            }
//        }

        // 图片
        if ( $this->req_msg_type == 'image' ) {

            $this->req_msg = (string)$request->PicUrl;
            // $this->req_msg = SITE_URL . '/proxy.php?type=qqimage&url='.$this->req_msg;
            // $this->req_msg = preg_replace('/http\:\/\/mmsns\.qpic\.cn/', 'http://proxyqqimage.alltosun.net', $this->req_msg);
            // $this->req_msg = preg_replace('/http\:\/\/mmbiz\.qpic\.cn/', 'http://proxyqqimage.alltosun.net', $this->req_msg);

            // 声音
        } elseif ( $this->req_msg_type == 'voice' ) {

            $this->req_msg = (string)$request->MediaId;

            // 位置
        } elseif ( $this->req_msg_type == 'location' ) {
            $this->req_msg = $request;

            // 事件(关注，取消关注，菜单点击)
        } elseif ( $this->req_msg_type == 'event' ) {
            $this->req_msg = $request;
            $this->req_msg_type = strtolower($request->Event);

            // 关注或取消关注
            if ($request->Event == 'SCAN') {
                $this->is_scan = TRUE;

            } else if ( $this->req_msg_type == 'subscribe' || $this->req_msg_type == 'unsubscribe') {

                if (isset($request->Ticket) && $request->Ticket) {
                    $this->is_scan = TRUE;
                }
                $this->req_msg              = (string)$this->req_msg_type;

                // 菜单点击
            } elseif ($this->req_msg_type == 'click') {
                $this->is_menu_event = TRUE;
                $event_key = (string)$request->EventKey;

                //@example key值为：V{$menu_id}_C_{$type}_{$appmsg_id}
                $event_key = explode('_', $event_key);

                $this->req_msg        = $event_key[3];
                $this->reply_msg_type = $event_key[2];

                appmenu_stat_helper::update_appmenu_stat(substr($event_key[0], 1), [], $this->company_id, $this->open_card_id);

            } elseif ($this->req_msg_type == 'location') {
                $this->req_msg   = (string)$request->Event;

                $this->need_response = FALSE;

                $this->is_city_sync = TRUE;
                $latitude = $request->Latitude;
                $longitude = $request->Longitude;
                $precision = $request->Precision;

                //$this->res_info['msg_type'] = 'text';
                //$this->res_info['content_str'] = $this->req_msg_type.' '.$latitude.' '.$longitude;

                // 群发的事件推送结果
            } elseif ($this->req_msg_type == strtolower('MASSSENDJOBFINISH')) {
                $this->need_response = FALSE;

                $mass_msg_id    = filter_string(trim($request->MsgID));
                $mass_status    = filter_string(trim($request->Status));
                $mass_total_count = (int)$request->TotalCount;
                $mass_filter_count = (int)$request->FilterCount;
                $mass_send_count = (int)$request->SentCount;
                $mass_error_count = (int)$request->ErrorCount;

                //写log调试
                $wx_resquest_log = array('msg_type'=>'test_push');

                WxRequestLog::create($wx_resquest_log);

                $tmp_info1 = array(
                    'mass_msg_id'           => $mass_msg_id,
                    'mass_status'           => $mass_status,
                    'mass_total_count'      => $mass_total_count,
                    'mass_filter_count'     => $mass_filter_count,
                    'mass_send_count'       => $mass_send_count,
                    'mass_error_count'      => $mass_error_count,
                );
                $wx_resquest_log = array('msg_type'=>'test_push');
                $wx_resquest_log['content'] = json_encode($tmp_info1);
                WxRequestLog::create($wx_resquest_log);

                // 根据群发后异步的通知，更新群发结果
                $update_mass_info = array();

                /*
                $wx_response = array(
                                'mass_status'           => $mass_status,
                                'mass_total_count'      => $mass_total_count,
                                'mass_filter_count'     => $mass_filter_count,
                                'mass_send_count'       => $mass_send_count,
                                'mass_error_count'      => $mass_error_count,
                );
                $update_mass_info['wx_response'] = json_encode($wx_response);
                */
                $update_mass_info['wx_response'] = $request_data;

                if ($mass_status == 'send success') {
                    $update_mass_info['progress'] = 20;
                    $update_mass_info['mass_total_count']      = $mass_total_count;
                    $update_mass_info['mass_filter_count']     = $mass_filter_count;
                    $update_mass_info['mass_send_count']       = $mass_send_count;
                    $update_mass_info['mass_error_count']      = $mass_error_count;
                } else {
                    $update_mass_info['progress'] = 15;
                }

                SendQueue::update($update_mass_info, ['wx_msg_id'=>$mass_msg_id]);
                SendThread::update($update_mass_info, ['wx_msg_id'=>$mass_msg_id]);

                // ========================
                // 通过wx_msg_id取到send_thread，如果所有thread都处理完毕，则更新send_queue =========
                // ========================
                $send_thread_info = get_res_info('send_thread', array('wx_msg_id'=>$mass_msg_id));
                if ($send_thread_info) {
                    $thread_num_filter = array(
                        'send_queue_id' => $send_thread_info['send_queue_id'],
                        'progress'      => 1
                    );
                    $send_thread_num = getTotal('send_thread', $thread_num_filter);
                    if ($send_thread_num < 1) {
                        $tmp_progress = $update_mass_info['progress'];
                        update_res_field('send_queue', (int)$send_thread_info['send_queue_id'], array('progress'=>$tmp_progress));
                    }
                }

                //写log调试
                $wx_resquest_log = array('msg_type'=>'test_push02', 'content'=>var_export($update_mass_info, true).' '.$mass_msg_id);
                WxRequestLog::create($wx_resquest_log);
            }

        } elseif ($this->req_msg_type == 'text') {
            //$this->req_msg = emotion_helper::parse_code(trim($request->Content));
            $this->req_msg = trim($request->Content);

        } else {
            $this->req_msg = serialize($request);

        }

        if (!$this->from_username || !$this->service_name  || !$this->req_msg_type || !$this->req_msg_timestamp || strlen($this->req_msg) == 0){
            throw new \Exception('xml请求数据$request_data解析后不完整。');
        }

        $is_first_subscribe = 0;

        // 该变量是用来控制，是否需要调用微信接口来取数据
        $need_get_wx_user = 0;

        if ($this->is_scan) {
            $this->scene_id = str_replace('qrscene_', '', (string)$request->EventKey);
            // foreach (qrode_config::$qrode_prefix as $k1=>$v1) {
            // }
            $this->ori_scene_id = $this->scene_id;
        }

        // 获取用户信息
        $user_info = _uri(
            'user',
            array(
                'open_id' => $this->from_username,
            )
        );
        if (!$user_info) {
            $need_get_wx_user = 1;

            // 创建用户
            $nickname  = '';
            //$nickname  = m_helper::get_wx_nickname($this->from_username);
            $user_info = array(
                'open_id'      => $this->from_username,
                //'nickname'     => $nickname,
                'is_subscribe' => 1,
                'status'       => 1
            );

            if ($this->is_scan && $this->scene_id) {
                $user_info['come_from'] = $this->scene_id;
            }

            // 第一次请求处理
            $this->is_first_request = true;

            // 之前关注的
            if ( $this->req_msg != weixin_config::$first_req_msg ) {
                $this->sub_before = true;
            } else {
                $is_first_subscribe = 1;

                $user_info['follow_time'] = date('Y-m-d H:i:s');
            }

            $user = User::create($user_info);
            $this->user_id   = $user->id;

            // 创建用户角色
            /*
            $role_id = _uri('role', array('type'=>90), 'id');
            // 创建role_user
            $role_user_info = array(
                'role_id'    => $role_id,
                'user_id'    => $this->user_id,
            );
            if (!_uri('role_user', $role_user_info)) {
                _model('role_user')->create($role_user_info);
            }
            */

        } else {
            $update_info = array();
            if ($this->is_scan && $this->scene_id) {
                $update_info['come_from'] = $this->scene_id;
            }

            $this->user_id = $user_info['id'];
            if ( $this->req_msg == weixin_config::$first_req_msg ) {

                $this->sub_again = true;

                $update_info['follow_time'] = date('Y-m-d H:i:s');
            }
            // 取消后再关注，更新follow_time
            if ($update_info) {
                User::update($update_info, ['open_id' => $this->from_username]);
            }

            // 如果没头像的，需要重新调用微信接口来取数据
            if (!isset($user_info['avatar']) || !$user_info['avatar'] || !$user_info['store_id']
                || ($user_info['follow_time'] == '0000-00-00 00:00:00' && !isset($update_info['follow_time']))) {
                $need_get_wx_user = 1;
            }
        }

        // 添加来源记录
        if ($this->is_scan && $this->scene_id) {
            $user_source_record = array(
                'open_card_id' => $this->open_card_id,
                'user_id'      => $this->user_id,
                'source'       => $this->scene_id
            );
            //user_helper::add_user_source_record($user_source_record);
        }

        //if ($is_first_subscribe == 1) {
        //$this->first_subscribe_score();
        //}
        $update_user_info = array();

//        if ($this->is_city_sync && ONDEV) {
//            $up_info = array(
//                'latitude_v' => $latitude,
//                'longitude_v' => $longitude,
//                'precision_v'=> $precision
//            );
//
//            // 通过经纬度取地理位置
//            if ($user_info && !$user_info['city_sync']) {
//                $city_sync = geocoder($latitude, $longitude);
//                if ($city_sync) {
//                    $up_info['city_sync'] = $city_sync;
//                }
//            }
//
//            $update_user_info = array_merge($update_user_info, $up_info);
//
//            // 定时上传地理位置的不用回复
//            $this->need_response = FALSE;
//        }

        // 重新获取微信用户的详细信息
        if ($need_get_wx_user == 1) {
            $wx_user_info = (new weixin_widget())->get_wx_user_info(array('open_id'=>$this->from_username));
            if ($wx_user_info && isset($wx_user_info['nickname'])) {
                // nickname表情转码
                $update_user_info['nickname'] = emotion_helper::emoji_to_code($wx_user_info['nickname']);
                $update_user_info['avatar'] = $wx_user_info['headimgurl'];

                // 老粉丝的关注时间
                if (isset($wx_user_info['subscribe_time'])) {
                    $update_user_info['follow_time'] = date('Y-m-d H:i:s', $wx_user_info['subscribe_time']);
                }
            }
        }

        // 如果不是扫码并且用户没有分组      处理用户标签的问题
        if ((!$this->is_scan || !$this->scene_id) && !$user_info['tag_id']) {
            // 如果不是扫码，该用户也没有关联store_id，此时根据该用户设置的省市来自动让他与某一个店铺产生关联
            /* if (isset($wx_user_info['country']) && $wx_user_info['country'] == '中国') {
                 $province_filter = array();
                 if (isset($wx_user_info['province']) && $wx_user_info['province']) {
                     $province_filter['province'] = $wx_user_info['province'];
                 }
                 if (isset($wx_user_info['city']) && $wx_user_info['city']) {
                     $province_filter['city'] = $wx_user_info['city'];
                 }

                 // 通过省市找到一个店铺 把用户分配到该店铺分组下
                 $province_store_info = store_helper::get_store_by_filter($province_filter);
                 if ($province_store_info) {
                     $update_user_info['store_id'] = $province_store_info['id'];
                     $store_info = get_res_info('store', $update_user_info['store_id']);
                     if ($store_info && $store_info['tag_id']) {
                         $group_data = array(
                             'user_id' => $this->user_id,
                             'group_id'  => $store_info['tag_id']
                         );

                         // 更改用户分组或标签
                         $res = _widget('weixin.tag')->change_user_group($group_data);
                         if ($res == 'ok') {
                             $update_user_info['tag_id'] = $store_info['tag_id'];
                         }
                     }
                 }
                 // 如果没有匹配到城市直接分组到全国标签下
             } else {
                 //已经被分组到全国标签下的用户不再中心分组

                 $group_data = array(
                     'user_id' => $this->user_id,
                     'group_id'  => 399
                 );
                 // 更改用户分组或标签
                 $res = _widget('weixin.tag')->change_user_group($group_data);

                 if ($res == 'ok') {
                     $update_user_info['tag_id'] = 399;
                 }

             }*/
//            $quan_guo_group_id = store_helper::get_quan_guo_group_id();  //线上399 线下123
//            $group_data = array(
//                'user_id' => $this->user_id,
//                'group_id'  => $quan_guo_group_id
//            );
//            // 更改用户分组或标签
//            $res = _widget('weixin.tag')->change_user_group($group_data);
//
//            if ($res == 'ok') {
//                $update_user_info['tag_id'] = $quan_guo_group_id;
//            }
        }

        if ($update_user_info) {
            User::update($update_user_info, ['id' => $this->user_id]);
        }

        // 记录所有用户请求信息
        /*
        $chat_info = array(
                    'company_id'   => $this->company_id,
                    'open_card_id' => $this->open_card_id,
                    'open_id'      => $this->from_username,
                    'msg_type'     => $this->req_msg_type,
                    'event_key'    => (string)$request->EventKey,
                    'content'      => $request->Content
                );
        chat_helper::create($chat_info);
        */

        $this->user_info = user_helper::get_user_info($this->user_id);

        // session
        $_SESSION['user_id'] = $this->user_id;
    }

    // 匹配自动图文
    private function fix_automsg()
    {
        $this->appmsg_list = (new appmsg_widget())->get_serialize_automsg(array('content'=>$this->res_info['content_str']));
        /* $this->res_info['msg_type'] = 'text';
        $this->res_info['content_str'] = '正在测试'.var_export($this->appmsg_list, true);
        return; */

        $this->res_info['msg_type'] = 'news';
        $this->res_info['content_str'] = '';
    }

    // 匹配营销策略
    private function fix_lottery($key_word)
    {
        /*
        $info = lottery_helper::get_lottery_by_key_word($key_word);
        if ($info) {
            $list = array();
            array_push($list, $info);
            $this->appmsg_list = $list;
        }
        $this->res_info['msg_type'] = 'news';
        $this->res_info['content_str'] = '';
        */
    }

    /**
     * 如果content是图文ID，则尝试查找
     */
    private function fix_real_content()
    {
        // 链接，换行符，表情替换,
        if ($this->res_info['msg_type'] != 'text' || !$this->res_info['content_str']) {
            return;
        }

        $this->res_info['content_str'] = html_entity_decode($this->res_info['content_str']);
        $this->res_info['content_str'] = $this->fix_link($this->res_info['content_str']);

        $this->res_info['content_str'] = preg_replace('/\<br.*?\>/', "<br>", $this->res_info['content_str']);
        //$this->res_info['content_str'] = trim($this->res_info['content_str'], '<br>');
        $this->res_info['content_str'] = preg_replace('/(<br>)+$/i', '', $this->res_info['content_str']);
        //return false;
        $this->res_info['content_str'] = str_replace('<br>', "\n", $this->res_info['content_str']);
        $this->res_info['content_str'] = strip_tags($this->res_info['content_str'], '<a><img>');

        $this->res_info['content_str'] = emotion_helper::image_to_str($this->res_info['content_str']);
    }

    /**
     * 发送微信
     * @param string $msg_type $msg_type = text/news  微信类型
     * @param 微信内容 $content_str
     * @param 微信图片 $msg_arr array(title, description, pic_url, url)
     */
    private function send($msg_type, $content_str, $msg_arr = array(), $is_star = false)
    {
        $content = "
            <xml>
                <ToUserName><![CDATA[".$this->from_username."]]></ToUserName>
                <FromUserName><![CDATA[".$this->service_name."]]></FromUserName>
                <CreateTime>".$this->add_time."</CreateTime>
                <MsgType><![CDATA[".$msg_type."]]></MsgType>";
        if ($msg_type == 'text') {
            $content .= "<Content><![CDATA[".$content_str."]]></Content>";
        } else if (in_array($msg_type, array('image'))) {
            $content .= "<Image><MediaId><![CDATA[".$content_str."]]></MediaId></Image>";
        } else if (in_array($msg_type, array('voice'))) {
            $content .= "<Voice><MediaId><![CDATA[".$content_str."]]></MediaId></Voice>";
        }

        $count = count($msg_arr);
        if ($count) {
            $content .= "<ArticleCount>".$count."</ArticleCount><Articles>";
            foreach ($msg_arr as $k=>$v) {

                if (strpos($v['cover'], 'http:/') === false) {
                    //@todo 第一条取大图
                    if ($k == 0) {
                        $v['cover'] = _image($v['cover'], 'big');

                        // 后面的条数取小图
                    } else {
                        $v['cover'] = _image($v['cover'], 'big');
                    }
                    if (strpos($v['cover'], SITE_URL) === false) {
                        $v['cover'] = SITE_URL.$v['cover'];
                    }
                }

                if (isset($v['link']) && strpos($v['link'], '&amp;') !== false) {
                    $v['link'] = htmlspecialchars_decode($v['link']);
                }

                //@todo 如果没有指定特殊的跳转地址，则指向该信息详情页
                if ($v['content_type'] == 2 && $v['content']) {
                    $v['link'] = url('/appmsg/m/'.$v['id'], [], true, true)->build();
                } else {
                    if (!$v['link']) {
                        $v['link'] = 'http://www.baidu.com';
                    }
                }

                if ($this->ori_scene_id) {
                    if (strpos($v['link'], '?') === false) {
                        //$v['link'] .= '?wx_id='.$this->user_id;
                        $v['link'] .= '?scene_id='.$this->ori_scene_id;
                    } else {
                        //$v['link'] .= '&wx_id='.$this->user_id;
                        $v['link'] .= '&scene_id='.$this->ori_scene_id;
                    }
                }

                $content.="<item>
                         <Title><![CDATA[".$v['title']."]]></Title>
                         <Description><![CDATA[".$v['intro']."]]></Description>
                         <PicUrl><![CDATA[".$v['cover']."]]></PicUrl>
                         <Url><![CDATA[".$v['link']."]]></Url>
                     </item>";
            }
            $content.="</Articles>";
        }

        // 是否星标
        if ($is_star) {
            $content.="<FuncFlag>1</FuncFlag></xml>";
        } else {
            $content.="<FuncFlag>0</FuncFlag></xml>";
        }
        Log::write($content);
        echo $content;
    }

    /**
     * 响应
     */
    private function response()
    {
        //$this->res_info['msg_type'] = 'text';
        //$this->res_info['content_str'] = $this->req_msg.'12121';
        //return false;
        //写log调试
        // 如果是关注或取消关注
        if ($this->req_msg == 'subscribe') {

            $this->qrcode_scan();
            if ($this->res_info['content_str'] || $this->appmsg_list) {
                //return false;
            } else {
                $this->fix_autoreply(1);
            }

            $sub_update_info = array(
                'is_subscribe'  =>  1,
                'follow_time'   =>  date('Y-m-d H:i:s')
            );

            User::update($sub_update_info, ['id' => $this->user_id]);
            $user_info = user_helper::get_user_info($this->user_id);
            if ($user_info) {
                // 添加关注的统计
                $subscribe_info = array(
                    'store_id'     => $user_info['store_id'],
                    'scene_id'     => $user_info['scene_id'],
                    'user_id'      => $this->user_id,
                    'open_id'      => $this->from_username,
                    'action'       => 1
                );
                (new subscribe_stat_widget())->create($subscribe_info);
            }

            // 取消关注
        } elseif ($this->req_msg == 'unsubscribe') {

            $user_info = user_helper::get_user_info($this->user_id);
            if ($user_info) {
                // 取消关注的统计
                $subscribe_info = array(
                    'store_id'     => $user_info['store_id'],
                    'scene_id'     => $user_info['scene_id'],
                    'user_id'      => $this->user_id,
                    'open_id'      => $this->from_username,
                    'action'       => 2
                );
                (new subscribe_stat_widget())->create($subscribe_info);
            }

            $this->need_response = FALSE;

            $sub_update_info = array(
                'tag_id'        => 0,       //把用户标签重新更新为0 重新关注时用新的tag_id
                'is_subscribe'  => 0,
                'follow_time'   => date('Y-m-d H:i:s'),
                'activity_id'   => 0,      // 取消关注时activity_id改为0，此id 代表门店id
                'store_id'      => 0    // 取消关注时把store_id改为0   此id 代表城市id
            );

            User::update($sub_update_info, ['id' => $this->user_id]);

            // 如果是扫码
        } elseif ($this->is_scan) {
            $this->qrcode_scan();

            // 如果菜单点击事件
        } elseif ($this->is_menu_event) {
            $this->res_info['content_str'] = '';

            if ($this->reply_msg_type == 1) {
                $this->res_info['content_str'] = '';
                $this->res_info['msg_type'] = 'news';
                $this->appmsg_list = index_msg_helper::get_index_msg_list();

                // 链接类型的
            } else if ($this->reply_msg_type == 10) {

                // 小程序类型的
            } else if ($this->reply_msg_type == 10) {

                // 纯文本
            } elseif ($this->reply_msg_type == 20) {
                $this->res_info['msg_type'] = 'text';
                $msg_info = get_res_info('appmenu', $this->req_msg);
                Log::write($msg_info);
                if ($msg_info) {
                    // 菜单来控制专属图片
//                    if ($msg_info['content'] == '生成海报') {
//                        $qrcode_img_info = poster_helper::get_qrcode_img_info($this->user_id);
//                        if ($qrcode_img_info) {
//                            if (!ONDEV && 1 == 2) {
//                                $this->res_info['msg_type'] = 'image';
//                                $this->res_info['content_str'] = poster_helper::get_qrcode_media_id($this->user_id);
//
//                            } else {
//                                $this->need_response == FALSE;
//
//                                //$this->need_seed_hai_bao = 1;
//
//                                //////////// ======= 锁开始
//                                $mc_wr = clone $GLOBALS['mc_wr'];
//                                $qrcode_img_lock = $mc_wr->NS('qrcode_lock', 1)->get('code_response'.$this->user_id);
//                                if ($qrcode_img_lock == 1) {
//                                    exit('');
//                                }
//                                $mc_wr->NS('qrcode_lock', 1)->set('code_response'.$this->user_id, 1, 15);
//                                //////////// ======= 锁结束
//
//
//                                $content = "你的海报将于".$qrcode_img_info['expire_time']."失效，过期后请点击【我要流量】->【生成海报】菜单重新获取哦。";
//                                $content .= "\n\n正在为您发送海报，请稍等...";
//
//                                // 发送文字 ====================
//                                $send_info = array(
//                                    'user_id'   => $this->user_id,
//                                    'type'      => 'text',
//                                    'content'  => $content
//                                );
//                                $flag = _widget('weixin')->send($send_info);
//
//                                //usleep(100);
//                                // 发送海报 ====================
//                                if ($flag == 'ok') {
//                                    //$this->need_seed_hai_bao = 0;
//
//                                    // 发送海报
//                                    poster_helper::push_poster($this->user_id);
//
//                                    $tmp_post_msg_id = 23;
//                                    if (!ONDEV) {
//                                        $tmp_post_msg_id = 310;
//                                    }
//                                    $tmp_appmsg_list = appmsg_helper::get_appmsg_list($tmp_post_msg_id);
//                                    if ($tmp_appmsg_list) {
//                                        $send_info = array(
//                                            'user_id'   => $this->user_id,
//                                            'type'      => 'news',
//                                            'msg_arr'  => $tmp_appmsg_list
//                                        );
//                                        $flag = _widget('weixin')->send($send_info);
//                                    }
//
//                                    $mc_wr->NS('qrcode_lock', 1)->set('code_response'.$this->user_id, 0, 1);
//                                }
//                            }
//                        } else {
//                            $this->need_response == FALSE;
//                        }
//                        //$this->res_info['msg_type'] = 'image';
//                        //$this->res_info['content_str'] = poster_helper::get_qrcode_media_id($this->user_id);
//                        //$this->res_info['content_str'] = '你好';
//
//                    } else {
                        $this->res_info['msg_type'] = 'text';
                        $this->res_info['content_str'] = $msg_info['content'];
//                    }
                }

                // 单图文 ,多图文
            } elseif (in_array($this->reply_msg_type, array(30, 40))) {
                $this->res_info['msg_type'] = 'news';
                $this->res_info['content_str'] = '';
                $this->appmsg_list = appmsg_helper::get_appmsg_list($this->req_msg);

            } elseif ($this->reply_msg_type == 50) {
                //$this->res_info['msg_type'] = 'text';
                //$this->res_info['content_str'] = $this->req_msg.'12121';
                $msg_info = get_res_info('appmenu', $this->req_msg);
                if ($msg_info) {
                    $this->res_info['content_str'] = $msg_info['content'];
                    $this->fix_automsg();
                }
            }

            // 普通的请求
        } elseif ($this->req_msg_type == 'text') {
            $this->res_info['msg_type'] = 'text';

//            if ($this->req_msg.'' == '位置' && ONDEV) {
//                $this->res_info['msg_type'] = 'text';
//                $city_sync = geocoder($latitude, $longitude);
//                if ($city_sync) {
//                    $this->user_info['city_sync'] = $city_sync;
//                }
//                $this->res_info['content_str'] = "位置：".$this->user_info['city_sync']."\n经度：".$this->user_info['latitude_v']."\n纬度：".$this->user_info['longitude_v'];
//                return;
//            }

            // 留言记录下来，便于统计
            $message_info = array(
                'user_id'      => $this->user_id,
                'open_id'      => $this->from_username,
                'content'      => $this->req_msg,
                'company_id'   => $this->company_id,
                'open_card_id' => $this->open_card_id,
            );

            (new message_widget())->create($message_info);

            // 找出关键词匹配的，然后拼出返回信息
            $autoreply_list = autoreply_helper::get_autoreply_list(3, 1, $this->open_card_id);
            // $this->res_info['content_str'] = var_export($autoreply_list, true);
            // return;
            if ($autoreply_list) {
                foreach ($autoreply_list as $k=>$v) {

                    // 折分关键词
                    $str = '';
                    $key_list = autoreply_helper::get_autoreply_key_list($v['id'], 2);

                    foreach ($key_list as $k1=>$v1) {
                        if (!$v1) {
                            continue;
                        }
                        $str = isset($v1['title']) ? trim($v1['title']) : '';
                        if (!$str) {
                            continue;
                        }

                        if (isset($v1['match_type']) && $v1['match_type'] == 2) {
                            $pattern = '/^('.$str.')$/';
                        } else {
                            $pattern = '/('.$str.')/';
                        }
                        /* $this->res_info['content_str'] = $v1['title'].' '.$v1['match_type'].' '.$pattern;
                        return; */

                        if (preg_match($pattern, $this->req_msg.'')) {
                            $reply_content_info = autoreply_helper::get_autoreply_rand_content($v['id']);

                            if ($reply_content_info) {
                                // 处理回复信息
                                $this->fix_autoreply(3, $reply_content_info);

                                // 关键词匹配数量加1
                                autoreply_helper::add_autoreply_key_match_num($v1['id']);
                                // 关键词统计加1
                                key_stat_helper::update_key_stat($v1['id'], array('title'=>$v1['title']), $this->company_id, $this->open_card_id);
                            }

                            break 2;
                        }
                    }
                }
            }

            $autoreply_list = autoreply_helper::get_autoreply_list(15, 1, $this->open_card_id);
            if ($autoreply_list) {
                foreach ($autoreply_list as $auto_key => $auto_val) {
                    $reply_content_info = autoreply_helper::get_autoreply_rand_content($auto_val['id']);
                    $this->fix_autoreply(15, $reply_content_info);
                }

            }

            // 如果关键词规刚没匹配上，看是否匹配到营销策略里面
        }

        if ($this->need_response == FALSE) {
            return false;
        }

        /* if ($this->res_info['msg_type'] == 'news' && !$this->appmsg_list) {
           $this->appmsg_list = array();
        } */
        // 取不能识别的自定义回复
        if (!$this->res_info['content_str'] && !$this->appmsg_list) {
            //$this->need_response = FALSE;
            //return;
            $this->fix_autoreply(2);
        }

        // 处理纯文本字符替换
        $this->fix_real_content();
    }

    /**
     * 匹配自动回复
     * @param int $type 1:关注欢迎语 2:无法识别时回复
     * @param array $content_info 关键词回复时特殊需要，需先取content_info
     */
    private function fix_autoreply($type = 1, $content_info = array())
    {
        if (!$content_info) {
            $content_info = autoreply_helper::get_autoreply_content_by_type($type, 1, $this->open_card_id, $this->company_id);
        }

        // 关联到首页
        if (!$content_info || $content_info['content_type'] == 0) {
            $this->res_info['content_str'] = '';
            //$this->res_info['msg_type'] = 'news';

            //$this->appmsg_list = index_msg_helper::get_index_msg_list();

            // 纯文本回复
        } else if ($content_info['content_type'] == 1) {
            $this->res_info['msg_type'] = 'text';
            $this->res_info['content_str'] = $content_info['content'];

            // 图文回复
        } else if ($content_info['content_type'] == 2 || $content_info['content_type'] == 3) {
            $this->res_info['content_str'] = '';
            $this->res_info['msg_type'] = 'news';
            $this->appmsg_list = appmsg_helper::get_appmsg_list($content_info['content']);
            // 智能回复
        } else if ($content_info['content_type'] == 4) {
            $this->res_info['content_str'] = $content_info['content'];
            $this->fix_automsg();

            // 纯图片
        } else if ($content_info['content_type'] == 10) {
//            appmedia_helper::update_appmedia($content_info['content'], 'image');
//            $this->res_info['msg_type']    = 'image';
//            $this->res_info['content_str'] = appmedia_helper::get_media_id($content_info['content']);

            // 活动
        } else if ($content_info['content_type'] == 40) {
            $this->res_info['msg_type'] = 'text';
            $reply_str = $this->get_act_content($content_info['content'], $this->req_msg, $this->from_username, $this->open_card_info['weixin_token']);        

        // $this->res_info['content_str'] = var_export(h_curl($link.'?'.$param), true);
        // return;
            $this->res_info['content_str'] = $reply_str;
            // 声音
        } else if ($content_info['content_type'] == 20) {
//            appmedia_helper::update_appmedia($content_info['content'], 'voice');
//            $this->res_info['msg_type'] = 'voice';
//            $this->res_info['content_str'] = appmedia_helper::get_media_id($content_info['content']);
        }
    }

    public function test()
    {
        var_dump(h_curl('http://192.168.2.109:1111/site_api/act/Wx_dragonboat21/Tread/test?keyword=test&tm=1624956200&openid=o37zejo4-mgEHELkUQ2dLR4hfMdc&sign=81136cbc41358f30ee73e2386475e4f4'));
    }
    protected function get_act_content($link, $keyword, $open_id, $token)
    {
        if(empty($link)){
            return '';
        }

//    $options = session('mp_options');
//    $token = $options['token'];
//    $openid = session('openid');
        $tmpArr = array('keyword'=>$keyword, 'tm'=>time(), 'openid'=>$open_id);
        $tmpArr['sign'] = $this->get_token($tmpArr, $token);
        $param = http_build_query($tmpArr, '', '&');

        return h_curl($link.'?'.$param);
    }

    protected function get_token($paramArr, $signKey, $dot = '&')
    {
        ksort($paramArr);
        $str = "";
        foreach($paramArr as $key=>$v){
            $str .= empty($str) ? $key . '=' . $v : $dot . $key . '=' . $v;
        }
        $sign = md5($str.$signKey);
        return $sign;
    }


    // 扫描带参二维码
    public function qrcode_scan()
    {
//        if ($this->is_scan && $this->scene_id) {
//
//            // 更改用户扫码scened_id
//            // ============================
//            $change_flag = 0;
//            if ($this->user_info && $this->user_info['is_subscribe'] != 1) {
//                $change_flag = 1;
//            }
//
//            $scan_store_id = 0;
//
//            // 检查该二维码是否存在
//            $qrode_info = qrode_helper::get_qrode_info_by_scene_id($this->scene_id);
//            if (!$qrode_info || !isset($qrode_info['store_id'])
//                || !isset($qrode_info['res_name']) || !isset($qrode_info['res_id'])) {
//                $this->scene_id = 0;
//                return false;
//            }
//
//            // 添加扫码记录
//            $qrode_record_info = array(
//                'qrode_id'      => $qrode_info['id'],
//                'res_name'      => $qrode_info['res_name'],
//                'res_id'        => $qrode_info['res_id'],
//                'user_id'       => $this->user_id
//            );
//            qrode_record_helper::add_record($qrode_record_info);
//
//            //解析获取活动id
//            $activity_id = 0;
//            //活动码为永久吗 参数为这种  ALLA_10756 格式
//            if (!is_numeric($this->scene_id)) {
//                $scene_arr  = explode('_', $this->scene_id);
//                if ($scene_arr[0] == 'ALLA') {
//                    $activity_id = $scene_arr[1] - 10000;        //此处10000是来自生成带参二维码里面的配置，活动码是用10000加上活动id
//                }
//            }
//
//            // 码对应的店铺id
//            $scan_store_id = $qrode_info['store_id'];
//
//            if (isset($this->user_info['store_id']) && $this->user_info['store_id'] >= 1 &&  $change_flag != 1) {
//
//                // 如果当前用户没有分配过scene_id，则给他初始化scene_id，因scene_id与store对应上的，所以即store_id
//            } else {
//                // 排除虚拟标签
//                if ($scan_store_id != 90) {
//                    $this->res_info['msg_type'] = 'text';
//                    $this->res_info['content_str'] = "你好，你的扫的码序号是".$this->user_info['store_id'].' '.$this->scene_id."\n".$scan_store_id;
//                    return false;
//
//                     ============================
//                     更改用户在公众平台那边的分组
//                     ============================
//                    $store_info = get_res_info('store', $scan_store_id);
//                    if ($store_info && $store_info['tag_id']) {
//                        $group_data = array(
//                            'user_id' => $this->user_id,
//                            'group_id'  => $store_info['tag_id']
//                        );
//
//                        // 更改用户分组或标签
//                        $res = _widget('weixin.tag')->change_user_group($group_data);
//                        //标签修改成功 更新用户的标签分组 店铺相关信息
//                        if ($res == 'ok') {
//                            $update_info = array(
//                                'tag_id'     => $store_info['tag_id'],
//                                'scene_id'   => $this->scene_id,
//                                'activity_id'   => $activity_id,
//                                'store_id'   => $scan_store_id
//                            );
//
//                            update_res_field('user', $this->user_id, $update_info);
//                        }
//                    }
//                }
//            }
//
//            // ============================
//            // 如果店铺的带参码设置了回复
//            // ============================
//            //$this->res_info['msg_type'] = 'text';
//            //$this->res_info['content_str'] = "你好，你的扫的码序号是".$this->scene_id."\n".var_export($scan_res_info, true);
//            //return false;
//            if ($qrode_info['response_type'] >= 1 && $qrode_info['response_content']) {
//                // 如果是图文回复
//                if (in_array($qrode_info['response_type'], array('30', '40'))) {
//                    $appmsg_list = appmsg_helper::get_appmsg_list((int)$qrode_info['response_content']);
//                    if ($appmsg_list) {
//                        $this->res_info['msg_type'] = 'news';
//                        $this->appmsg_list = $appmsg_list;
//                    }
//                } else {
//                    $this->res_info['msg_type'] = 'text';
//                    $this->res_info['content_str'] = $qrode_info['response_content'];
//                }
//            }
//
//            $this->scene_id = 0;
//        }
    }

    /**
     * 校正链接后的参数
     */
    private function fix_link($str)
    {
        return $str;
        if (strpos($str, 'wx_id=wx_id') !== false) {
            //$str = str_replace('wx_id=wx_id', 'wx_id='.$this->user_id, $str);
        }

        $reg = '/(http[^\x{4e00}-\x{9fa5}\s]+)/u';
        $flag = preg_match_all($reg, $str, $matches);
        if ($flag && isset($matches[1]) && $matches[1]) {
            $unique_arr = array_unique($matches[1]);
            foreach($unique_arr as $k=>$v) {
                if (strpos($v['link'], '?') === false) {
                    $tmp_link = $v.'?wx_id='.$this->user_id;
                } else {
                    $tmp_link = $v.'&wx_id='.$this->user_id;
                }
                $tmp_link = $v;
                $str = str_replace($v, '<a href="'.$tmp_link.'">'.$v.'</a>', $str);
            }
        }

        return $str;

        /* $pattern = '/href="http:\/\/(.*?)"/';
        $flag = preg_match_all($pattern, $str, $matches);
        //var_dump($flag, $matches);
        if ($flag && isset($matches[1])) {
            foreach ($matches[1] as $v) {
                if (strpos($v, '?') === false) {
                    $str = str_replace($v, $v.'?wx_id='.$this->user_id, $str);
                } else {
                    $str = str_replace($v, $v.'&wx_id='.$this->user_id, $str);
                }
            }
        }

        return $str; */
    }

    /**
     * 解析公司信息
     * @throws Exception
     */
    private function parse_company()
    {
        $open_card_info = open_card_helper::unsign_open_card_key(Request::get('wx_c', ''));
        if (!$open_card_info) {
            //send_email( 'qianym@alltosun.com', 'wei400: parse_company_error', Request::Get('wx_c', '') );
            throw new \Exception('解析公司出错，没有此公司');
        }

        $this->open_card_info = $open_card_info;
        $this->open_card_id   = $this->open_card_info ? $this->open_card_info['id'] : 0;
        $this->company_id     = $open_card_info['company_id'];
    }

    ////////////////////////////
    // 微信接口首次接入验证
    ////////////////////////////

    /**
     * 测试通信是否正常
     */
    private function valid()
    {
        $echo_str = Request::get('echostr');

        //valid signature , option
        if($this->check_signature()){
            echo $echo_str;
        }
    }

    private function check_signature()
    {
        $signature = Request::get('signature', '');
        $timestamp = Request::get('timestamp', '');
        $nonce     = Request::get('nonce', '');

        $token = $this->open_card_info['weixin_token'];
        // 按字典排序后sha1加密
        $tmp_arr = array($token, $timestamp, $nonce);
        sort($tmp_arr);
        $tmp_str = implode( $tmp_arr );
        $tmp_str = sha1( $tmp_str );

        $email_title = ' 验证结果';
        if( $tmp_str == $signature ){
            $email_content = ' 验证结果：成功';
            //send_email('test@xxx.com', $email_title, $email_content);
            return true;
        }

        $email_content = ' 验证结果：失败';
        //send_email('test@xxxx.com', $email_title, $email_content);

        return false;
    }
}